Published on

CSS 병합 이슈 해결기

Authors
  • avatar
    Name
    CDD
    Twitter

서론

현 프로젝트 구조

project-root/
  ├── node_modules/
  │   ├── @company/
  │   │   ├── page1/
  │   │   ├── page2/
  │   │   ├── page3/
  │   │

페이지 단위로 빌드되어 프로젝트로 들어가는 구조인 상황에서 저희가 사용하고 있는 CSS 라이브러리는 바로 tailwindcss인데요, 각 페이지들이 빌드되면 tailwindcsspurge 기능을 이용해서 output.css를 만듭니다. 대충 아래와 같은 느낌의 파일이겠죠?

.h-10 {
  height: 2.5rem;
}

.h-2 {
  height: 0.5rem;
}

.h-3 {
  height: 0.75rem;
}

.h-3\.5 {
  height: 0.875rem;
}

.h-32 {
  height: 8rem;
}

.h-4 {
  height: 1rem;
}

그런데 페이지가 많아지게 되면서 저렇게 output으로 빌드되는 css 파일들이 정말 많이 생기게 되었는데요, 여기서 문제가 하나 생깁니다. w-full h-full과 같이 자주 사용되는 className들은 모두 중복되어 import 된다는 것이었죠.

그냥 무시하고 돌리면 안되나? 성능에 그렇게 영향이 있나?

modal

있더군요, 우선 디버깅을 위해 개발자 콘솔을 여니 3초 간 반응이 없다가 개발자 콘솔이 강제종료 되더군요. 어찌저찌 페이지들을 줄여서 열어봐도 스크롤을 한참 내려야 적용되는 스타일링의 끝이 보였습니다. 페이지가 20개라면 20개의 속성이 동시 적용되고, inherit 받는 css도 함께 출력되고 하면서 급속도로 불아나기 시작하는거죠.

그래서?

우선 빌드된 모든 페이지들의 css를 한 파일로 묶어 중복된 className이 발생하면 없애주는 작업이 필요했습니다. 이걸 어떻게 만들까 하다가 터미널에서 cat 명령어를 통해 css 파일들을 모두 합친 뒤, purge를 통해 중복 제거해서 만들어진 하나의 css만을 넣어야겠다고 생각했습니다. 그렇게 된다면 스타일링이 중복되는 경우는 없겠죠.

해결방식

1. 모든 css 파일 combine 하기

merge-css.sh
company_packages=$(grep -o '"@company[^"]*"' package.json | sed 's/"//g')

# combined.css 파일 만들기
> combined.css

for package in $company_packages; do
  css_file="node_modules/$package/dist/output.css"
  if [ -f "$css_file" ]; then
    cat "$css_file" >> combined.css
  else
    echo "Warning: $css_file not found."
  fi
done

echo "All CSS files have been combined into combined.css."

셸 스크립트까지 직접 구현하는 건 리소스 낭비라는 생각이 들어 지피티에게 최대한 자세히 설명해주면서 스크립트를 받아냈습니다, 약간의 커스텀도 들어갔지만요.

2. 중복을 제거하는 작업, purge

purge-css.sh
if [ -f "combined.css" ]; then
  css-purge -i combined.css -o purged.css
  echo "combined.css has been purged and output to purged.css."
else
  echo "Error: combined.css not found. Please run merge-css.sh first."
fi

css-purge라는 라이브러리를 사용했는데요, 처음 테스트를 해봤을 때 저희가 직접 커스텀한 css 속성들까지 넣으니 purge error가 뜨더군요. 아마 컴파일 상에는 css 내 문법 오류가 있어도 어느정도는 그냥 넘어가는 것이 있지만, css-purge는 약간의 문법오차가 존재한다면 곧바로 오류가 뜹니다. 그래서 export 하는 css는 무조건 tailwind 관련으로만 한정 지었고, 그렇게 구현하니 문제 없이 purge가 진행되었습니다.

3. package.jsonscript 작성

이제 돌릴 때마다 위의 스크립트들이 작동하도록 해주어야겠죠?

package.json
{
  "license": "MIT",
  "scripts": {
    "prebuild": "node ./scripts/generate-pages.js && yarn merge-css && yarn purge-css"
  },
// other settings
}

결론

modalmodal

좌측이 수정 전 버전, 우측이 수정 후 버전입니다. 훨씬 겹치는 거 없이 깔끔하게 뜨는 모습을 볼 수 있습니다. 이제는 크롬 개발자 도구도 잘 살아 있네요. 처음에는 그냥 root에서 빌드하면서 모든 프로젝트들을 한 번에 purge 시킬까 고민했다가 그렇게 하니 빌드가 멈춰버려서 포기하고 위와 같은 방법으로 진행했습니다. 가려웠던 부분이 해결되어 기쁘군요.